// "a (b c 1 nil null) true [] 'str"
// {
// 	type:"jisp",
// 	value:[
// 		{type:"jisp-symbol",value:"a"},
// 		{
// 			type:"jisp",
// 			value:[
// 					{type:"jisp-symbol",value:"b"},
// 					{type:"jisp-symbol",value:"c"},
// 					1,
// 					null,
// 					null
// 			]
// 		},
// 		true,
// 		[],
// 		"str"
// 	]
// }

;(function(exports,r){
	var head=r.head;
	var tail=r.tail;
	var pipe=r.pipe;
	var map=r.map;
	var last=r.last;
	var reduce=r.reduce;
	//jisp基础数据类型
	var makeToken=r.cond([
			[isString,makeString],
			[isNumberToken,makeNumber],
			[isBooleanToken,makeBoolean],
			[isNilToken,r.always(null)],
			[isArrayToken,makeArray],
			[isJispToken,makeJisp],
			[r.T,makeSymbol]
		]);
	function not(a){
		return !a;
	}
	//去头去尾
	var tailInit=r.pipe(tail,r.init);
	function isNumberToken(a){
		return not(isNaN(Number(a)));
	}
	function makeNumber(str){
		return Number(str);
	}
	function isString(str){
		return head(str)=="'";
	}
	function makeString(str){
		return tail(str);
	}
	function isBooleanToken(str){
		return str=="true"||str=="false";
	}
	function makeBoolean(str){
		if(str=="true")return true;
		return false;
	}
	function isNilToken(str){
		return str=="nil"||str=="null";
	}
	function isArrayToken(str){
		return head(str)=="["&&last(str)=="]";
	}
	function makeArray(str){
		return parseToken(tailInit(str));
	}
	function isJispToken(str){
		return head(str)=="("&&last(str)==")";
	}
	function isSymbol(obj){
		return obj&&obj.type=="jisp-symbol";
	}
	function makeSymbol(a){
		return {
			type:"jisp-symbol",
			value:a
		}
	}
	function isJisp(obj){
		return obj&&obj.type=="jisp";
	}
	function makeJisp(str){
		return {
			type:"jisp",
			value:parseToken(tailInit(str))
		}
	}

	function isTokenEnd(endpro,ttoken){
		return endpro[0].apply(null,r.concat(tail(endpro),[ttoken]));
	}
	function isJispEnd(num,ttoken){
		return num==1&&ttoken==")";
	}
	function isArrayEnd(num,ttoken){
		return num==1&&ttoken=="]";	
	}
	function _parseToken(str,token,endpro){
		//jisp结束
		if(r.isEmpty(str)){
			if(head(endpro)==isArrayEnd) throw "jisp-> array缺少右括号->"+token;
			if(head(endpro)==isJispEnd) throw "jisp-> jisp缺少右括号->"+token;
			if(r.isEmpty(token)) return [];
			return [makeToken(token)];
		}
		var ttoken=head(str);
		if(isTokenEnd(endpro,ttoken)){
			if(ttoken==")")token+=")";
			if(ttoken=="]")token+="]";
			return r.concat([makeToken(token)],_parseToken(tail(str),"",[r.F]));
		}
		if(r.equals(endpro,[r.F])){
			if(ttoken=="("){
				return _parseToken(tail(str),token+ttoken,[isJispEnd,1]);
			}
			if(ttoken=="["){
				return _parseToken(tail(str),token+ttoken,[isArrayEnd,1]);
			}
			if(ttoken==" ") return _parseToken(tail(str),"",[r.F]);;
			return _parseToken(tail(str),token+ttoken,[r.equals," "]);
		}
		if(head(endpro)==isArrayEnd){
			if(ttoken=="["){
				endpro[1]++;
			}
			if(ttoken=="]"){
				endpro[1]--;
			}
		}
		if(head(endpro)==isJispEnd){
			if(ttoken=="("){
				endpro[1]++;
			}			
			if(ttoken==")"){
				endpro[1]--;
			}
		}
		return _parseToken(tail(str),token+ttoken,endpro);
	}

	function parseToken(str){
		return _parseToken(str,"",[r.F]);
	}
	function getJispFn(jisp){
		var symbol = head(jisp.value);
		if(isSymbol(symbol)){
			return getSymbol(symbol);
		}
		throw "jisp-> 函数名字必须是符号（非数字布尔nil null)";
	}
	function getJispArgs(jisp){
		return tail(jisp.value);
	}
	function getSymbol(symbol){
		return symbol.value;
	}
	//宏
	var jispMacro={
		testmacro:function(a,b,c){
			return parser("(test ("+getSymbol(a)+" "+b+" "+c+")");
		}
	};
	function isJispMacro(symbol){
		return jispMacro[symbol]!=null;
	}
	function getJispMacro(symbol){
		return jispMacro[symbol];
	}
	function runMacro(symbol,args){
		return getJispMacro(symbol).apply(null,args);
	}
	function parseMacro(jisp){
		if(isJisp(jisp)){
			if(isJispMacro(getJispFn(jisp))){
				return runMacro(getJispFn(jisp),getJispArgs(jisp));
			}
			return jisp;
		}
		return jisp;
	}
	function run(){
	}
	function parser(str){
		console.time("time")
		var t= parseToken(str);
		var r=parseMacro(last(t));
		console.timeEnd("time");
		return r;
	}
	exports.jisp={
		run:run,
		parser:parser,
		evail:r.pipe(parser,run)
	}
}(this,R));


